<template>
  <div class="video-player">
    <div class="video-container">
      <!-- 视频播放区域 -->
      <video
        ref="videoRef"
        :autoplay="autoplay"
        :muted="muted"
        :controls="controls"
        @loadstart="onLoadStart"
        @loadeddata="onLoadedData"
        @canplay="onCanPlay"
        @error="onError"
        @ended="onEnded"
        @pause="onPause"
        @play="onPlay"
      >
        您的浏览器不支持视频播放
      </video>
      
      <!-- 加载状态 -->
      <div v-if="showLoading" class="loading-overlay">
        <div class="loading-content">
          <el-icon class="loading-icon"><Loading /></el-icon>
          <div class="loading-text">加载中...</div>
        </div>
      </div>
      
      <!-- 错误状态 -->
      <div v-if="showError" class="error-overlay">
        <div class="error-content">
          <el-icon class="error-icon"><Warning /></el-icon>
          <div class="error-text">{{ error }}</div>
          <el-button size="small" @click="retry" class="retry-button">重试</el-button>
        </div>
      </div>
      
      <!-- Seek 状态 -->
      <div v-if="isSeeking" class="seeking-overlay">
        <div class="seeking-content">
          <el-icon class="seeking-icon"><Loading /></el-icon>
          <div class="seeking-text">时间跳转中...</div>
        </div>
      </div>
      
      <!-- 无视频源 -->
      <div v-else-if="!videoUrl && !showLoading && !showError" class="no-video-overlay">
        <div class="no-video-content">
          <el-icon class="no-video-icon"><VideoCamera /></el-icon>
          <div class="no-video-text">暂无视频</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onUnmounted, computed } from 'vue'
import { ElIcon, ElButton } from 'element-plus'
import {
  Loading,
  Warning,
  VideoCamera
} from '@element-plus/icons-vue'
import mpegts from 'mpegts.js'

interface Props {
  videoUrl?: string
  width?: number | string
  height?: number | string
  autoplay?: boolean
  muted?: boolean
  controls?: boolean
  showCustomControls?: boolean
}

// 码流统计信息接口
interface StreamStats {
  bitrate: number
  fps: number
  resolution: string
  bufferHealth: number
}

const props = withDefaults(defineProps<Props>(), {
  width: 640,
  height: 360,
  autoplay: false,
  muted: true,
  controls: false,
  showCustomControls: false
})

// 容器样式现在完全由CSS控制

// 定义事件
const emit = defineEmits<{
  'stream-stats-update': [stats: StreamStats]
}>()

// 组件状态
const videoRef = ref<HTMLVideoElement>()
const loading = ref(false)
const error = ref('')
const isSeeking = ref(false)

// 计算属性：确保状态不冲突
const showLoading = computed(() => loading.value && !error.value)
const showError = computed(() => error.value && !loading.value)

// 强制状态管理函数
const setError = (errorMsg: string) => {
  error.value = errorMsg
  loading.value = false // 强制清除加载状态
}

const setLoading = (isLoading: boolean) => {
  if (isLoading && !error.value) {
    loading.value = true
  } else if (!isLoading) {
    loading.value = false
  }
}

// FLV 播放器实例
let flvPlayer: any = null

// 码流统计信息
const streamStats = ref<StreamStats>({
  bitrate: 0,
  fps: 0,
  resolution: '',
  bufferHealth: 0
})

// FPS计算相关变量
let lastDecodedFrames = 0
let lastFpsTime = Date.now()

// 统计信息更新定时器
let statsInterval: number | null = null

// VideoPlayer 专门用于播放 FLV 流

// 更新码流统计信息
const updateStreamStats = (statisticsInfo: any) => {
  if (!statisticsInfo || !videoRef.value) return
  
  try {
    // 计算码率 (Kbps) - statisticsInfo.speed 通常是以字节/秒为单位
    const bitrate = statisticsInfo.speed || 0
    const bitrateKbps = bitrate > 0 ? Math.round((bitrate * 8) / 1000 * 100) / 100 : 0
    
    // 获取视频分辨率
    const videoElement = videoRef.value
    const resolution = videoElement.videoWidth && videoElement.videoHeight 
      ? `${videoElement.videoWidth}x${videoElement.videoHeight}` 
      : ''
    
    // 计算FPS - 基于decodedFrames的时间差计算
    const decodedFrames = statisticsInfo.decodedFrames || 0
    const droppedFrames = statisticsInfo.droppedFrames || 0
    const currentTime = Date.now()
    
    let fps = 0
    if (lastDecodedFrames > 0 && decodedFrames > lastDecodedFrames) {
      const timeDiff = (currentTime - lastFpsTime) / 1000 // 转换为秒
      const frameDiff = decodedFrames - lastDecodedFrames
      fps = timeDiff > 0 ? Math.round(frameDiff / timeDiff) : 0
    }
    
    // 更新FPS计算基准
    lastDecodedFrames = decodedFrames
    lastFpsTime = currentTime
    
    // 计算丢帧率（可选，用于调试）
    const dropRate = decodedFrames > 0 ? Math.round((droppedFrames / decodedFrames) * 100) : 0
    
    // 计算缓冲区健康度
    const bufferHealth = videoElement.buffered.length > 0 
      ? Math.round((videoElement.buffered.end(videoElement.buffered.length - 1) - videoElement.currentTime) * 100) / 100
      : 0
    
    // 只在有实际数据变化时更新
    const newStats = {
      bitrate: bitrateKbps,
      fps: Math.round(fps),
      resolution,
      bufferHealth
    }
    
    // 检查是否有数据变化
    const hasChanges = 
      streamStats.value.bitrate !== newStats.bitrate ||
      streamStats.value.fps !== newStats.fps ||
      streamStats.value.resolution !== newStats.resolution ||
      streamStats.value.bufferHealth !== newStats.bufferHealth
    
    if (hasChanges) {
      streamStats.value = newStats
      
      // 发射统计信息更新事件
      emit('stream-stats-update', streamStats.value)
      
      console.log('码流统计更新:', streamStats.value)
      console.log('丢帧率:', dropRate + '%', '总解码帧:', decodedFrames, '丢帧数:', droppedFrames)
    }
  } catch (error) {
    console.error('更新码流统计信息失败:', error)
  }
}

// 开始统计信息监控
const startStatsMonitoring = () => {
  if (statsInterval) {
    clearInterval(statsInterval)
  }
  
  statsInterval = window.setInterval(() => {
    if (flvPlayer && videoRef.value && !videoRef.value.paused) {
      // 定期更新统计信息
      const videoElement = videoRef.value
      if (videoElement.videoWidth && videoElement.videoHeight) {
        const resolution = `${videoElement.videoWidth}x${videoElement.videoHeight}`
        const bufferHealth = videoElement.buffered.length > 0 
          ? Math.round((videoElement.buffered.end(videoElement.buffered.length - 1) - videoElement.currentTime) * 100) / 100
          : 0
        
        // 只在分辨率或缓冲健康度发生变化时更新
        if (streamStats.value.resolution !== resolution || streamStats.value.bufferHealth !== bufferHealth) {
          streamStats.value = {
            ...streamStats.value,
            resolution,
            bufferHealth
          }
          
          // 发射统计信息更新事件
          emit('stream-stats-update', streamStats.value)
        }
      }
    }
  }, 2000) // 每2秒更新一次，减少频率
}

// 停止统计信息监控
const stopStatsMonitoring = () => {
  if (statsInterval) {
    clearInterval(statsInterval)
    statsInterval = null
  }
}

// 初始化FLV播放器 - 参考 StreamPlayerDialog 实现
const initFlvPlayer = async () => {
  if (!videoRef.value || !props.videoUrl) {
    console.error('FLV播放器初始化失败: 缺少必要的元素或URL')
    return
  }
  
  // 确保之前的播放器已经完全清理
  if (flvPlayer) {
    console.log('检测到已有播放器实例，先清理')
    await stopPlay()
    await new Promise(resolve => setTimeout(resolve, 300))
  }
  
  try {
    console.log('开始初始化FLV播放器，URL:', props.videoUrl)
    console.log('URL类型:', typeof props.videoUrl)
    console.log('URL长度:', props.videoUrl?.length)
    console.log('URL包含端口:', props.videoUrl?.includes(':'))
    
    if (mpegts.isSupported()) {
      console.log('浏览器支持mpegts.js')
      
      // 在创建播放器前再次确认URL
      console.log('创建mpegts播放器前的URL:', props.videoUrl)
      console.log('URL解析测试:', new URL(props.videoUrl))
      
      flvPlayer = mpegts.createPlayer({
        type: 'flv',
        isLive: true,
        url: props.videoUrl,
        cors: true,
        withCredentials: false
      })
      
      flvPlayer.on(mpegts.Events.ERROR, (errType: any, errInfo: any, errDetail: any) => {
        console.error('mpegts播放错误:', errType, errInfo, errDetail)
        console.error('错误类型:', errType)
        console.error('错误信息:', errInfo)
        console.error('错误详情:', errDetail)
        console.error('当前URL:', props.videoUrl)
        console.error('URL是否包含端口:', props.videoUrl?.includes(':'))
        loading.value = false
        
        // 根据错误类型设置错误信息
        if (errInfo && errInfo.code === -1 && errInfo.msg === 'Failed to fetch') {
          setError('网络连接失败，请检查网络或流地址')
        } else if (errInfo && errInfo.msg) {
          setError(`播放失败: ${errInfo.msg}`)
        } else if (errType === 'NetworkError') {
          setError('网络错误，请检查流地址是否可访问')
        } else if (errType === 'MediaError') {
          setError('媒体错误，请检查流格式')
        } else {
          setError(`视频流播放失败: ${errType}`)
        }
      })
      
      flvPlayer.on(mpegts.Events.LOADING_COMPLETE, () => {
        console.log('mpegts加载完成')
        loading.value = false
      })
      
      flvPlayer.on(mpegts.Events.MEDIA_INFO, (mediaInfo: any) => {
        console.log('mpegts媒体信息:', mediaInfo)
        // 当获取到媒体信息时，说明流已经开始加载，可以隐藏加载遮罩
        loading.value = false
      })
      
      flvPlayer.on(mpegts.Events.STATISTICS_INFO, (statisticsInfo: any) => {
        console.log('mpegts统计信息更新:', statisticsInfo)
        // 当有统计信息时，说明流正在播放，确保隐藏加载遮罩
        loading.value = false
        
        // 更新码流统计信息（减少更新频率）
        if (statisticsInfo.speed > 0) {
          updateStreamStats(statisticsInfo)
        }
      })
      
      console.log('关联媒体元素:', videoRef.value)
      flvPlayer.attachMediaElement(videoRef.value)
      
      console.log('开始加载流')
      flvPlayer.load()
      
      // 等待流加载完成后再播放
      await new Promise(resolve => setTimeout(resolve, 500))
      
      console.log('开始播放')
      try {
        await flvPlayer.play()
        console.log('FLV播放成功启动')
      } catch (playErr: any) {
        console.warn('播放失败，可能是浏览器限制:', playErr)
        // 如果自动播放失败，等待用户交互
        if (playErr.name === 'NotAllowedError') {
          console.log('自动播放被阻止，等待用户交互')
        } else if (playErr.name === 'AbortError') {
          console.log('播放被中断，可能是快速重启导致')
          // 对于AbortError，我们不需要抛出错误，因为这是正常的
        } else {
          throw playErr
        }
      }
      
      // 开始统计信息监控
      startStatsMonitoring()
      
      // 设置超时确保加载遮罩被隐藏
      setTimeout(() => {
        if (loading.value) {
          console.warn('FLV视频加载超时，停止加载状态')
          setError('FLV视频加载超时，请检查网络连接或流地址')
        }
      }, 15000) // 增加到15秒超时，给FLV流更多加载时间
      
    } else {
      throw new Error('当前浏览器不支持FLV播放')
    }
  } catch (err) {
    console.error('FLV播放器初始化失败:', err)
    loading.value = false
    throw err
  }
}

// 停止播放
const stopPlay = async () => {
  console.log('开始停止播放')
  
  // 停止统计信息监控
  stopStatsMonitoring()
  
  if (flvPlayer) {
    try {
      // 先暂停播放
      if (videoRef.value && !videoRef.value.paused) {
        console.log('暂停视频播放')
        videoRef.value.pause()
      }
      
      // 等待更长时间确保暂停完成
      await new Promise(resolve => setTimeout(resolve, 500))
      
      // 销毁播放器
      console.log('销毁FLV播放器')
      flvPlayer.destroy()
      flvPlayer = null
    } catch (err) {
      console.warn('停止播放时出现错误:', err)
      // 强制销毁
      if (flvPlayer) {
        flvPlayer.destroy()
        flvPlayer = null
      }
    }
  }
  
  if (videoRef.value) {
    console.log('重置视频元素')
    videoRef.value.src = ''
    videoRef.value.load() // 重置视频元素
  }
  
  // 重置统计信息
  streamStats.value = {
    bitrate: 0,
    fps: 0,
    resolution: '',
    bufferHealth: 0
  }
  
  console.log('停止播放完成')
}

// 加载FLV视频流
const loadVideo = async () => {
  console.log('loadVideo被调用')
  console.log('videoRef存在:', !!videoRef.value)
  console.log('videoUrl:', props.videoUrl)
  
  if (!props.videoUrl) {
    console.log('无法加载视频：缺少videoUrl')
    return
  }
  
  // 如果videoRef还没准备好，等待一下再试
  if (!videoRef.value) {
    console.log('videoRef未准备好，延迟重试')
    setTimeout(() => {
      loadVideo()
    }, 200) // 增加等待时间
    return
  }
  
  console.log('videoRef已准备好，开始加载FLV流')
  
  // 先停止之前的播放，等待完成
  await stopPlay()
  
  // 等待更长时间确保停止完成
  await new Promise(resolve => setTimeout(resolve, 300))
  
  error.value = ''
  setLoading(true)
  
  try {
    console.log('使用mpegts.js播放FLV流')
    await initFlvPlayer()
  } catch (err) {
    console.error('FLV流加载失败:', err)
    loading.value = false
    
    // 根据错误类型设置更具体的错误信息
    if (err instanceof Error) {
      if (err.message.includes('Failed to fetch') || err.message.includes('NetworkError')) {
        setError('网络连接失败，请检查网络或流地址')
      } else if (err.message.includes('timeout')) {
        setError('连接超时，请检查网络连接')
      } else {
        setError(`FLV流加载失败: ${err.message}`)
      }
    } else {
      setError('FLV流加载失败')
    }
  }
}

// 监听视频地址变化
watch(() => props.videoUrl, (newUrl) => {
  if (newUrl) {
    loadVideo()
  } else {
    error.value = ''
    loading.value = false
  }
}, { immediate: true })

// 事件处理
const onLoadStart = () => {
  setLoading(true)
}

const onLoadedData = () => {
  console.log('视频数据加载完成')
  loading.value = false
  // 清除错误状态，因为数据已加载完成
  error.value = ''
}

const onCanPlay = () => {
  console.log('视频可以播放')
  loading.value = false
  error.value = ''
}

const onError = (event: Event) => {
  console.error('视频加载错误:', event)
  
  // 获取更详细的错误信息
  const video = event.target as HTMLVideoElement
  if (video && video.error) {
    const errorCode = video.error.code
    const errorMessage = video.error.message
    console.error('视频错误代码:', errorCode)
    console.error('视频错误信息:', errorMessage)
    
    // 如果是错误代码4且src为空，这通常是在重置视频元素时触发的，可以忽略
    if (errorCode === 4 && errorMessage.includes('Empty src attribute')) {
      console.log('忽略视频重置时的错误')
      return
    }
    
    switch (errorCode) {
      case 1:
        setError('视频加载被中止')
        break
      case 2:
        setError('网络错误导致视频下载失败')
        break
      case 3:
        setError('视频解码错误')
        break
      case 4:
        setError('视频格式不支持')
        break
      default:
        setError(`视频加载失败 (错误代码: ${errorCode})`)
    }
  } else {
    setError('视频加载失败')
  }
}

const onEnded = () => {
  // 视频播放结束
}

const onPause = () => {
  // 视频暂停
}

const onPlay = () => {
  // 视频播放
}

const retry = async () => {
  console.log('重试按钮被点击')
  console.log('当前视频URL:', props.videoUrl)
  console.log('当前错误状态:', error.value)
  
  try {
    // 清除错误状态和加载状态
    error.value = ''
    loading.value = false
    
    // 等待一小段时间确保状态清除完成
    await new Promise(resolve => setTimeout(resolve, 200))
    
    // 重新加载FLV流
    if (videoRef.value && props.videoUrl) {
      await loadVideo()
      console.log('重新加载FLV流:', props.videoUrl)
    } else {
      console.log('无法重试：videoRef或videoUrl为空')
      setError('无法重试：缺少视频源')
    }
  } catch (err) {
    console.error('重试时发生错误:', err)
    setError(`重试失败: ${err instanceof Error ? err.message : '未知错误'}`)
  }
}

// 暴露给父组件的方法和数据
// 暂停播放
const pauseVideo = () => {
  if (flvPlayer && videoRef.value && !videoRef.value.paused) {
    console.log('暂停视频播放')
    videoRef.value.pause()
    return true
  }
  return false
}

// 恢复播放
const resumeVideo = async () => {
  if (flvPlayer && videoRef.value && videoRef.value.paused) {
    console.log('恢复视频播放')
    try {
      await flvPlayer.play()
      return true
    } catch (err) {
      console.warn('恢复播放失败:', err)
      return false
    }
  }
  return false
}

// 切换播放状态
const togglePlayPause = async () => {
  if (videoRef.value) {
    if (videoRef.value.paused) {
      return await resumeVideo()
    } else {
      return pauseVideo()
    }
  }
  return false
}

// 处理 seek 操作
const handleSeek = async () => {
  console.log('VideoPlayer: 开始 seek 操作')
  isSeeking.value = true
  
  // 设置一个较长的延迟，确保 seek 操作完成
  setTimeout(() => {
    isSeeking.value = false
    console.log('VideoPlayer: seek 操作完成')
  }, 2000)
}

defineExpose({
  streamStats,
  stopPlay,
  loadVideo,
  pauseVideo,
  resumeVideo,
  togglePlayPause,
  handleSeek
})

// 组件卸载时清理FLV播放器
onUnmounted(async () => {
  await stopPlay()
})
</script>

<style scoped>
.video-player {
  position: relative;
  background: #000;
  border-radius: 6px;
  overflow: hidden;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box; /* 确保边框和内边距包含在尺寸内 */
}

.video-container {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  position: absolute;
  top: 0;
  left: 0;
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
  z-index: 10;
}

.error-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
  z-index: 20; /* 错误状态优先级更高 */
}

.seeking-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
  z-index: 15;
}

.no-video-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
  z-index: 15;
}

.loading-content,
.error-content,
.no-video-content,
.seeking-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: white;
}

.loading-icon,
.error-icon,
.no-video-icon,
.seeking-icon {
  font-size: 32px;
  margin-bottom: 16px;
}

.loading-icon {
  color: #409eff;
  animation: spin 1s linear infinite;
}

.error-icon {
  color: #f56c6c;
}

.no-video-icon {
  color: #909399;
}

.seeking-icon {
  color: #409eff;
  animation: spin 1s linear infinite;
}

.loading-text,
.error-text,
.no-video-text,
.seeking-text {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
  margin-bottom: 16px;
}

.retry-button {
  margin-top: 8px;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
</style>